from django.db import models
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from garetjax.db.models import OrderedModel
from django.template.defaultfilters import slugify
import os, re
from PIL import Image

def import_folder(folder, set):
    from django.core.files import File
    from django.core.files.storage import default_storage
    
    match_re = re.compile(r'^\.|_thumb\.\w{3,4}$')
    
    for f in os.listdir(folder):
        full_file = os.path.join(folder, f)
        if os.path.isfile(full_file) and not match_re.search(f):
            new_photo = Photo(set=set)
            new_file = open(full_file)
            new_photo.photo = default_storage.save(UploadPath.photo(new_photo, f), File(new_file))
            new_photo.save()
            new_file.close()

class UploadPath:
    @staticmethod
    def photo(instance, filename):
        """
        Defines the upload path for each photo, based on the name of the set of
        the photo.
        """
        
        directory = '%04d-%s' % (instance.set.id, slugify(instance.set.title))
        
        regex = r'.*?(\d+-|temp-)?(?P<filename>[\w_ ()-]+)\.(?P<extension>\w{3,4})$'
        pathinfo = re.compile(regex).match(filename).groupdict()
        
        if instance.id:
            filename = '%05d-%s.%s' % (instance.id, slugify(pathinfo['filename']), pathinfo['extension'])
        else:
            filename = 'temp-%s.%s' % (slugify(pathinfo['filename']), pathinfo['extension'])
            
        return os.path.join('assets/photos', directory, filename)
    
    @staticmethod
    def photo_thumb(instance, filename):
        path = UploadPath.photo(instance, filename)
        return '-thumb.'.join(path.rsplit('.', 1))
    
    @staticmethod
    def collection_thumb(instance, fn):
        filename = '%04d-%s-thumb.jpg' % (instance.id, slugify(instance.title))
        return os.path.join('assets/photos', filename)
    
    @staticmethod
    def set_thumb(instance, fn):
        directory = '%04d-%s' % (instance.id, slugify(instance.title))
        filename = 'thumbnail.jpg'
        return os.path.join('assets/photos', directory, filename)

class Collection(OrderedModel):
    """
    A collection is a container for sets or other collections.
    Collections can be nested.
    """
    title = models.CharField(max_length=100)
    description = models.TextField(blank=True)
    key_photo = models.ForeignKey('Photo', related_name='key_of_collection', blank=True, null=True)
    thumbnail = models.ImageField(max_length=200, blank=True, null=True, editable=False, upload_to=UploadPath.collection_thumb)
    date_added = models.DateTimeField(auto_now_add=True)
    parent = models.ForeignKey('self', blank=True, null=True)
    
    def photos(self):
        return Photo.objects.filter(set__collection__id=self.pk)
    photos = property(photos)
    
    def save(self, **options):
        if self.key_photo is None and self.photos.count():
            self.key_photo = self.photos.all()[0]
        
        if self.key_photo:
            from garetjax.gallery.utils import generate_thumbnail
        
            path = UploadPath.collection_thumb(self, self.key_photo.photo.name)
            abs_path = os.path.join(settings.MEDIA_ROOT, path)
        
            try:
                generate_thumbnail(Image.open(self.key_photo.photo.path), settings.IMAGE_COLLECTION_THUMB_SIZE).save(abs_path, 'JPEG')
            except IOError:
                pass
        
            self.thumbnail = path
        
        super(Collection, self).save(**options)
    
    def __unicode__(self):
        if self.parent:
            return u'%s/%s' % (unicode(self.parent), self.title)
        else:
            return self.title

class Set(models.Model):
    """
    A set is an album. It contains photos and CAN BE part of a collection.
    Albums can't be nested.
    """
    title = models.CharField(_('title'), max_length=100)
    description = models.TextField(_('descrizione'), blank=True)
    date_added = models.DateTimeField(auto_now_add=True)
    key_photo = models.ForeignKey('Photo', related_name='key_of_set', blank=True, null=True)
    thumbnail = models.ImageField(max_length=200, blank=True, null=True, editable=False, upload_to=UploadPath.collection_thumb)
    collection = models.ForeignKey(Collection, verbose_name=_('collezione'), blank=True, null=True, related_name='sets')
    
    @models.permalink
    def get_absolute_url(self):
        return ('photos.photo', (), {'photo_id': self.id})
    
    def save(self, **options):
        if self.key_photo is None and self.photos.count():
            self.key_photo = self.photos.all()[0]
        
        if self.key_photo:
            from garetjax.gallery.utils import generate_thumbnail
        
            path = UploadPath.set_thumb(self, self.key_photo.photo.name)
            abs_path = os.path.join(settings.MEDIA_ROOT, path)
        
            try:
                generate_thumbnail(Image.open(self.key_photo.photo.path), settings.IMAGE_SET_THUMB_SIZE).save(abs_path, 'JPEG')
            except IOError:
                pass
        
            self.thumbnail = path
        
        super(Set, self).save(**options)
    
    def __unicode__(self):
        if self.parent:
            return u'%s/%s' % (unicode(self.parent), self.title)
        else:
            return self.title
    def __unicode__(self):
        return self.title
    

class Photo(models.Model):
    """
    A Photo is a single item of an album. Photos must be part of a set.
    """
    title = models.CharField(blank=True, max_length=100)
    description = models.TextField(blank=True)
    date_added = models.DateTimeField(auto_now_add=True)
    set = models.ForeignKey(Set, related_name='photos')
    photo = models.ImageField(max_length=200, upload_to=UploadPath.photo, height_field='height', width_field='width')
    height = models.PositiveIntegerField(blank=True, null=True)
    width = models.PositiveIntegerField(blank=True, null=True)
    thumbnail = models.ImageField(max_length=200, blank=True, null=True, editable=False, upload_to=UploadPath.photo_thumb)
    
    def __unicode__(self):
        return u'%s' % self.title or self.photo.name.rsplit('/').pop()
    
    @models.permalink
    def get_absolute_url(self):
        return ('photos.photo', (), {'photo_id': self.id})
    
    def get_next_in_set(self):
        try:
            return Photo.objects.filter(date_added__gt=self.date_added).filter(set=self.set).exclude(id=self.id)[0]
        except IndexError:
            return None
    
    def get_previous_in_set(self):
        try:
            return Photo.objects.filter(date_added__lt=self.date_added).filter(set=self.set).exclude(id=self.id).order_by('-date_added')[0]
        except IndexError:
            return None
    
    def save(self):
        if not self.id:
            # Save to get an ID
            super(Photo, self).save()
        
        if self.photo.name.find('temp-'):
            # Rename the file
            from django.core.files.storage import default_storage
            old_path = self.photo.path
            self.photo = default_storage.save(UploadPath.photo(self, self.photo.path), self.photo)
            super(Photo, self).save()
            os.remove(old_path)
        
        from garetjax.gallery.utils import generate_thumbnail
        from PIL import Image
        
        path = UploadPath.photo_thumb(self, self.photo.name)
        abs_path = os.path.join(settings.MEDIA_ROOT, path)
        
        try:
            generate_thumbnail(Image.open(self.photo.path), settings.IMAGE_THUMB_SIZE).save(abs_path, 'JPEG')
        except IOError:
            pass
        
        self.thumbnail = path
        
        super(Photo, self).save()
    
    class Meta:
        ordering = ('date_added',)
